#include "Vector.h"

/// Funções do vetor ///
Vector3::Vector3(void)
{
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        (*this)(i) = 0;
}

Vector3::Vector3(float x, float y, float z)
{
    (*this)(0) = x;
    (*this)(1) = y;
    (*this)(2) = z;
    (*this)(3) = 0;
}

void Vector3::imprimir(void) const
{
    cout<<"(";
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
    {
        cout<<(*this)(i);
        if(i < NUMERO_ELEMENTOS-1)
            cout<<" , ";
    }
    cout<<")"<<endl;
}

Vector3 Vector3::operator+(const Vector3 & other) const
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i) + other(i);
    return(aux);
}

Vector3 Vector3::operator-(const Vector3 & other) const
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i) - other(i);
    return(aux);
}

float Vector3::length() const
{
    return(sqrt(squaredLength()));
}

float Vector3::squaredLength() const
{
    float resultado = 0;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        resultado += pow((*this)(i),2);
    return(resultado);
}


/// Funções do ponto ///
Point3::Point3(void)
{
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        (*this)(i) = 0;
    (*this)(NUMERO_ELEMENTOS-1) = 1;
}

Point3::Point3(float x, float y, float z)
{
    (*this)(0) = x;
    (*this)(1) = y;
    (*this)(2) = z;
    (*this)(3) = 1;
}

Point3::Point3(const Vector3 & vector)
{
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        (*this)(i) = vector(i);
    (*this)(NUMERO_ELEMENTOS-1) = 1;
}

void Point3::imprimir(void) const
{
    cout<<"(";
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
    {
        cout<<(*this)(i);
        if(i < NUMERO_ELEMENTOS-1)
            cout<<" , ";
    }
    cout<<")"<<endl;
}

Point3 Point3::operator+(const Vector3 & vector) const
{
    Point3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i) + vector(i);
    return(aux);
}

Vector3 Point3::operator-(const Point3 & other) const
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i) - other(i);
    return(aux);
}

Vector3 Point3::toVector3() const
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i);
    aux(NUMERO_ELEMENTOS-1) = 0;
    return(aux);
}


/// Funções extras ///
Vector3 operator&(const Vector3 & v1, const Vector3 & v2)
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = v1(i) * v2(i);
    return(aux);
}

float dotProduct(const Vector3 & v1, const Vector3 & v2)
{
    float resultado = 0;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        resultado += v1(i) * v2(i);
    return(resultado);
}

float operator^(const Vector3 & v1, const Vector3 & v2)
{
    return(dotProduct(v1,v2));
}

Vector3 crossProduct(const Vector3 & v1, const Vector3 & v2)
{
    Vector3 aux;
    aux(0) = v1(1) * v2(2) - v1(2) * v2(1);
    aux(1) = v1(2) * v2(0) - v1(0) * v2(2);
    aux(2) = v1(0) * v2(1) - v1(1) * v2(0);
    return(aux);
}

Vector3 operator*(const Vector3 & v1, const Vector3 & v2)
{
    return(crossProduct(v1,v2));
}

Vector3 Vector3::normalize() const
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = (*this)(i) / length();
    return(aux);
}

Vector3 operator*(float value, const Vector3 & vector)
{
    Vector3 aux;
    for(int i=0 ; i<NUMERO_ELEMENTOS ; i++)
        aux(i) = value * vector(i);
    return(aux);
}

Vector3 operator*(const Vector3 & vector, float value)
{
    return(value * vector);
}

Vector3 operator/(const Vector3 & vector, float value)
{
    return((1/value) * vector);
}
